<?php

namespace App\Http\Controllers\Home\Index\Api;

use DB;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Model\Sort;
use App\Model\Goods;
use App\Model\Sale_promotion;
use App\Model\FriendLink;
use App\Model\Company;
use Illuminate\Support\Facades\Redis;


class IndexApi extends Controller
{   
    /**
     * 查询所有分类
     * @author wuboheng 
     * @return [array] [所有分类的数组]
     */
    public function loadSort()
    {   

        //先从Redis查找分类信息,如果有则return回去
        if (Redis::get('indexSort')){
            // dd(json_decode(Redis::get('indexSort'), true));
            return json_decode(Redis::get('indexSort'), true);  //把json字符串转化成数组return出去
        }

        //找出根分类
        $sortList = Sort::select(['id', 'sname', 'pid', 'state', 'updated_at'])->where('pid', 0)->where('state', 1)->get()->toArray();

        // dd($sortList);

        //找出二级分类并放入根分类对象的subSort属性中
        foreach($sortList as &$v){

            $id2 = $v['id'];
            $subSortObj = Sort::select(['id', 'sname', 'pid', 'state', 'updated_at'])->where('pid', $id2)->where('state', 1)->get()->toArray();

            //找出三级分类并放入二级分类对象的thirdSort属性中
            foreach($subSortObj as &$v2){

                $id3 = $v2['id'];
                $thirdSortObj = Sort::select(['id', 'sname', 'pid', 'state', 'updated_at'])->where('pid', $id3)->where('state', 1)->get()->toArray();

                if(!empty($thirdSortObj)){

                    $v2['thirdSort'] = $thirdSortObj;  //放置三级分类

                }
            }

            if(!empty($subSortObj)){

                $v['subSort'] = $subSortObj;  //放置二级分类
            }

            // $arr = $sortList;
            Redis::set('indexSort', json_encode($sortList));   //把数据存入Redis
            Redis::expire('indexSort', 60*60*24*7);    //设置Redis的key时间为7天
            
        }

        // dd($sortList);
        return $sortList;
    }

    /**
     * loadCarousels  遍历最新轮播图的信息,限定查询5条
     * @author wuboheng 
     * @return array 轮播图的信息,包含对应产品id,图片路径
     */
    public function loadCarousels ()
    {   
        //先从Redis里面找
        if(Redis::get('indexCarousels')){

            return json_decode(Redis::get('indexCarousels'));
        }

        $carousel = DB::table('carousels')
            ->select(['id', 'gid', 'path', 'updated_at'])
            ->where('state', 0)
            ->orderBy('updated_at', 'desc')
            ->limit(5)  //限制查询5条
            ->get()
            ->toArray();

        Redis::set('indexCarousels', json_encode($carousel));
        Redis::expire('indexCarousels', 60*60*24);  //24小时刷新一次

        // dd($carousel);
        return $carousel;

    }

    /**
     * 查找轮播图隔壁侧栏的促销小图
     * @author wuboheng 
     * @return array 促销小图信息,包括对应促销商品id,价格id,排序权重,促销图片路径
     */
    public function loadAsidePromotion ()
    {   
        //先从Redis查询
        if (Redis::get('indexAsidePromotion')) {

            return json_decode(Redis::get('indexAsidePromotion'));
        }

        //获取当前时间
        $nowTime = time();

        $asidePromotion = DB::table('sale_promotion')
            ->select(['id', 'gid', 'pid', 'sale_sort', 'path'])
            ->where('state', '1')
            ->where('ad_address', 4)    //4代表广告位置是轮播图隔壁侧栏的促销图
            ->where('sale_end_time', '>', $nowTime)
            ->orderBy('sale_sort', 'desc')
            ->limit(2)    //只搜索2个
            ->get()
            ->toArray();

        Redis::set('indexAsidePromotion', json_encode($asidePromotion));
        Redis::expire('indexAsidePromotion', 60*60*2);  //2小时刷新一次

        return $asidePromotion;

    }

    /**
     * 查找'特惠促销'栏的促销信息
     * @param  [int] $x [水平方向促销图片的个数]
     * @param  [int] $y [垂直方向促销图片的个数]
     * @return [array]    [促销栏信息,包括对应促销商品id,价格id,排序权重,促销图片路径,促销价格]
     */
    public function loadHomePromotion($x, $y)
    {

        if (Redis::get('homePromotion')) {

            // dd(json_decode(Redis::get('homePromotion'), true));
            return json_decode(Redis::get('homePromotion'), true);
        }    

        //获取当前时间
        $nowTime = time();

        //查找水平方向的3个促销
        $homePromotionX = Sale_promotion::select(['id', 'gname', 'gid', 'pid', 'sale_sort', 'path', 'sale_price'])   
            ->where('ad_address', 2)    //2代表广告位置是特惠促销水平位置的3个大图
            // ->where('sale_end_time', '>', $nowTime)
            ->where('state', '1')
            ->orderBy('sale_sort', 'desc')
            ->limit($x)    //只搜索3个
            ->get();
            // ->toArray();

        $homePromotionY = Sale_promotion::select(['id', 'gname', 'gid', 'pid', 'sale_sort', 'path', 'sale_price'])
            ->where('ad_address', 3)    //3代表广告位置是特惠促销垂直位置的2个小图
            // ->where('sale_end_time', '>', $nowTime)
            ->where('state', '1')
            ->orderBy('sale_sort', 'desc')
            ->limit($y)    //只搜索3个
            ->get();
            // ->toArray();

        $homePromotion['xPromot'] = $homePromotionX->toArray();
        $homePromotion['yPromot'] = $homePromotionY->toArray();

        //存进Redis
        Redis::set('homePromotion', json_encode($homePromotion));
        Redis::expire('homePromotion', 60*60*1);   //每1个小时刷新一次

        // dd($homePromotion);
        return $homePromotion;

    }

    /**
     * 首页热卖促销栏目的信息
     * @author wuboheng <[email address]>
     * @return [array] [热卖促销栏目的信息]
     */
    public function loadHotSale()
    {   
        if (Redis::get('homeHotSale')) {

            return json_decode(Redis::get('homeHotSale'), true);
        }
        
        // if (Redis::get('homeHotSale')) {

        //     return view('Admin/Goods/test', ['data' => json_decode(Redis::get('homeHotSale'), true) ]);
        // }

        $nowTime = time();

        $hotSale = Sale_promotion::select(['id', 'gid', 'pid', 'gname', 'sale_price', 'path'])
            ->where('ad_address', 1)
            ->where('state', '1')
            ->where('sale_end_time', '>', $nowTime)
            ->orderBy('sale_sort', 'desc')
            ->get()
            ->toArray();

        Redis::set('homeHotSale', json_encode($hotSale));
        Redis::expire('homeHotSale', 60*60*2);     //每2个小时刷新一次

        return $hotSale;
        
        // return view('Admin/Goods/test', ['data' => $hotSale ]);
    }


    /**
     * 递归遍历获取某一级分类及其全部附属子类别的所有商品
     * @author 吴伯恒
     * @param  [int] $sortid  [某一级分类的分类id]
     * @param  [object] $sortObj [子类别的对象,调用时无需手动传递此参数]
     * @return [array]          [某一分类底下的所有商品]
     */
    public function findGoodsBySort($sortid = null, $sortObj = null)
    {   
        //用于存放商品的数组
        $result = [];

        //如果是通过分类id进来的参数:
        if ($sortid !== null) {

            //查找该类别(假设此分类叫一级分类)
            $sortOne = Sort::find($sortid);
            // dd($sortOne);
            
            //查找此一级分类是否有下级分类(假设叫二级分类)
            $sortTwo = $sortOne->findSonSort;
            // dd($sortTwo);

            //如果没有二级分类,则把一级分类底下的所有商品搜出来
            if ($sortTwo->isEmpty()) {

                //==========  此部分是未用Redis改良过的代码  ===============
                //
                // $goods = $sortOne->findGoods()
                //     ->select(['id', 'gname', 'price', 'sid', 'pic', 'sales', 'click', 'state'])
                //     ->where('state', 1)
                //     ->OrWhere('state', 4)
                //     ->get()
                //     ->toArray();
                //   
                // 拿到一级分类的商品并且返回  
                // $result = array_merge($result, $goods);
                // return $result;
                // 
                //==========================================================
                
                //==========  以下代码用Redis改良过  ===============
                //获取一级分类底下所有商品的id
                $gids = $sortOne->findGoods()
                    ->pluck('id')
                    ->toArray();

                $gidArr = [];   //用于存放Redis没有信息的那些商品的id
                //循环商品id,根据id从Redis里面找寻商品信息,如果找到则返回,找不到则从数据库查询
                foreach ($gids as $gid) {

                    if ( Redis::get('goodsData:'. $gid) ) {

                        //需要用[0][0]才能把从Redis里面拿到的一维数组变成二维数组,从而让格式符合array_merge合并成商品信息的二维数组$result
                        $demo[0][0] = json_decode(Redis::get('goodsData:'. $gid), true);
                        // dd($demo[0][0]);
                        //如果在Redis里面有数据,则合并起来,组成$result返回出去
                        $result = array_merge($result, $demo[0]);

                    } else {

                        //如果Redis没有数据,则把gid存起来,然后在后续代码通过数据库查询对应的商品信息
                        $gidArr[] = $gid;
                    }

                }

                //查询数据库,把Redis没有的商品查出来
                $goods = Goods::select(['id', 'gname', 'price', 'sid', 'pic', 'sales', 'click', 'state'])
                    ->whereIn('id', $gidArr)
                    ->where('state', 1)
                    ->OrWhere('state', 4)
                    ->get()
                    ->toArray();

                //循环goods,把每一个商品存入Redis
                foreach ($goods as $k => $v) {
                    $demo[0] = $v;
                    Redis::set('goodsData:'. $v['id'], json_encode($demo[0]));
                    Redis::expire('goodsData:'. $v['id'], 60*60*24);    //每24个小时刷新一次
                }

                // dd($goods);
                
                //拿到一级分类的商品并且返回
                $result = array_merge($result, $goods);
                // dd($result);
                return $result;

                //==========================================================
                
            } else {
                //否则,是存在二级分类的: 
                
                //==========  此部分是未用Redis改良过的代码  ===============
                //先把一级分类的商品搜索出来
                // $goods = Goods::select(['id', 'gname', 'price', 'sid', 'pic', 'sales', 'click', 'state'])
                // ->where('sid', $sortid)
                // ->where('state', 1)
                // ->OrWhere('state', 4)
                // ->get()
                // ->toArray();
                // //拿到一级分类商品
                // $result = array_merge($result, $goods);

                // //*****重点一步********
                // //递归调用本函数,把所有二级分类当做第二参数传递,然后循环遍历当中的分类,如此类推
                // $result = array_merge($result, $this->findGoodsBySort(null, $sortTwo));
                // return $result;
                //===============================================================
                
                //==========  以下代码用Redis改良过  ===============
                //先把一级分类的商品id搜索出来
                $gids = Goods::where('sid', $sortid)
                    ->where('state', 1)
                    ->OrWhere('state', 4)
                    ->pluck('id')
                    ->toArray();

                // dd($gids);

                $gidArr = [];   //用于存放Redis没有信息的那些商品的id
                //遍历商品id,尝试从Redis里面取商品数据,如果取得到,则合并到$result,取不到,则查询数据库
                foreach ($gids as $gid) {

                    //尝试从Redis拿数据
                    if ( Redis::get('goodsData:'. $gid) ) {

                        //如果从Redis拿到商品数据,则存入$result
                        $demo[0][0] = json_decode( Redis::get('goodsData:'. $gid), true );
                        // dd($demo[0][0]);
                        $result = array_merge($result, $demo[0]);

                    } else {
                        //拿不到数据,则把id存起来,在后续代码查询数据库
                        $gidArr[] = $gid;
                    }

                }
                // dd($result, $gidArr);

                //查询数据库,把Redis没有的商品查出来
                $goods = Goods::select(['id', 'gname', 'price', 'sid', 'pic', 'sales', 'click', 'state'])
                    ->whereIn('id', $gidArr)
                    ->where('state', 1)
                    ->OrWhere('state', 4)
                    ->get()
                    ->toArray();

                //循环goods,把每一个商品存入Redis
                foreach ($goods as $k => $v) {
                    $demo[0] = $v;
                    Redis::set('goodsData:'. $v['id'], json_encode($demo[0]));
                    Redis::expire('goodsData:'. $v['id'], 60*60*24);    //每24个小时刷新一次
                }

                // dd($gids);

                // 拿到一级分类商品
                $result = array_merge($result, $goods);

                //*****重点一步********
                //递归调用本函数,把所有二级分类当做第二参数传递,然后循环遍历当中的分类,如此类推
                $result = array_merge($result, $this->findGoodsBySort(null, $sortTwo));
                return $result;

                //==================================================

            }
        }

        //*****重点一步********
        //如果是传对象(二级分类)进来,则循环遍历该分类的商品(若有)和它的二级分类(若有)
        if ($sortObj !== null) {

            //遍历二级分类
            foreach ($sortObj as $value) {
                
                //把二级分类的id取出,根据此id(当做第一参数)再次递归调用本函数,一层一层找到所有的商品
                $result = array_merge($result, $this->findGoodsBySort($value->id, null));
            }

            return $result;

        }
        
    }

    /**
     * 获取友情链接的数据
     * @return [array] [友情链接的数据(5条)]
     */
    public function loadFriendLink()
    {   
        if (Redis::get('friendLink')) {

            return json_decode(Redis::get('friendLink'), true);
        }

        $friendLink = FriendLink::select(['id', 'name', 'http_address', 'content'])
            ->limit(5)
            ->get()
            ->toArray();

        // dd($friendLink);
        
        Redis::set('friendLink', json_encode($friendLink));
        Redis::expire('friendLink', 60*60*24*30);     //每30天刷新一次
        
        return $friendLink;
    }


    /**
     * 获取公司信息
     * @return [array] [公司信息]
     */
    public function loadCompany()
    {   
        if (Redis::get('company')) {

            return json_decode(Redis::get('company'), true);
        }

        $company = Company::first()
            ->toArray();

        // dd($company);
        
        Redis::set('company', json_encode($company));
        Redis::expire('company', 60*60*24*30);     //每30天刷新一次
        
        return $company;
    }

    //============================================================================

    /**
     * 重置首页热卖促销栏目的信息的Redis
     * @author wuboheng <[email address]>
     * @return [array] [热卖促销栏目的信息]
     */
    public function setHotSale()
    {   
        
        $nowTime = time();

        $hotSale = Sale_promotion::select(['id', 'gid', 'pid', 'gname', 'sale_price', 'path'])
            ->where('ad_address', 1)
            ->where('state', '1')
            ->where('sale_end_time', '>', $nowTime)
            ->orderBy('sale_sort', 'desc')
            ->get()
            ->toArray();

        Redis::set('homeHotSale', json_encode($hotSale));
        Redis::expire('homeHotSale', 60*60*2);     //每2个小时刷新一次

    }


    /**
     * 重置轮播图隔壁侧栏的促销小图的Redis
     * @author wuboheng 
     * @return array 促销小图信息,包括对应促销商品id,价格id,排序权重,促销图片路径
     */
    public function setAsidePromotion()
    {   

        //获取当前时间
        $nowTime = time();

        $asidePromotion = DB::table('sale_promotion')
            ->select(['id', 'gid', 'pid', 'sale_sort', 'path'])
            ->where('state', '1')
            ->where('ad_address', 4)    //4代表广告位置是轮播图隔壁侧栏的促销图
            ->where('sale_end_time', '>', $nowTime)
            ->orderBy('sale_sort', 'desc')
            ->limit(2)    //只搜索2个
            ->get()
            ->toArray();

        Redis::set('indexAsidePromotion', json_encode($asidePromotion));
        Redis::expire('indexAsidePromotion', 60*60*2);  //2小时刷新一次

    }


    /**
     * 重置'特惠促销'栏的促销信息的Redis
     * @param  [int] $x [水平方向促销图片的个数]
     * @param  [int] $y [垂直方向促销图片的个数]
     * @return [array]    [促销栏信息,包括对应促销商品id,价格id,排序权重,促销图片路径,促销价格]
     */
    public function setHomePromotion()
    {
        // DB::table('score')
        //     ->insert(['relation' => 3.3]);

        //获取当前时间
        $nowTime = time();

        //查找水平方向的3个促销
        $homePromotionX = Sale_promotion::select(['id', 'gname', 'gid', 'pid', 'sale_sort', 'path', 'sale_price'])   
            ->where('ad_address', 2)    //2代表广告位置是特惠促销水平位置的3个大图
            // ->where('sale_end_time', '>', $nowTime)
            ->where('state', '1')
            ->orderBy('sale_sort', 'desc')
            ->limit(3)    //只搜索3个
            ->get();
            // ->toArray();

        $homePromotionY = Sale_promotion::select(['id', 'gname', 'gid', 'pid', 'sale_sort', 'path', 'sale_price'])
            ->where('ad_address', 3)    //3代表广告位置是特惠促销垂直位置的2个小图
            // ->where('sale_end_time', '>', $nowTime)
            ->where('state', '1')
            ->orderBy('sale_sort', 'desc')
            ->limit(2)    //只搜索2个
            ->get();
            // ->toArray();

        $homePromotion['xPromot'] = $homePromotionX->toArray();
        $homePromotion['yPromot'] = $homePromotionY->toArray();

        //存进Redis
        Redis::set('homePromotion', json_encode($homePromotion));
        Redis::expire('homePromotion', 60*60*3);   //每3个小时刷新一次

        // dd($homePromotion);

    }

    /**
     * 清除首页懒加载的Redis(清除6个版块)
     * @return [void] []
     */
    public function delLazyLoadRedis()
    {
        //清除首页懒加载的Redis
        Redis::del('lazyLoad:0');
        Redis::del('lazyLoad:1');
        Redis::del('lazyLoad:2');
        Redis::del('lazyLoad:3');
        Redis::del('lazyLoad:4');
        Redis::del('lazyLoad:5');
    }

    /**
     * 清除Top30的某个Redis数据
     * @return [void] []
     */
    public function delHotDataByGid($gid)
    {
        Redis::hDel('hotData', 'hotData:'.$gid);
    }







}
